package com.dd.cloud.user.service.admin.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.auth.req.role.UserBindRoleReq;
import com.dd.cloud.common.constants.AdminConstants;
import com.dd.cloud.common.constants.HealthConstants;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.common.utils.Assert;
import com.dd.cloud.common.utils.CodecUtils;
import com.dd.cloud.common.utils.SerialNumberUtils;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.user.entity.admin.*;
import com.dd.cloud.user.feign.AuthFeignService;
import com.dd.cloud.user.mapper.admin.AdminSaleInfoMapper;
import com.dd.cloud.user.req.admin.AdminSaleInfoCreateReq;
import com.dd.cloud.user.req.admin.AdminSaleInfoPageReq;
import com.dd.cloud.user.req.admin.AdminSaleInfoUpdateReq;
import com.dd.cloud.user.res.admin.AdminSaleInfoDetailRes;
import com.dd.cloud.user.res.admin.AdminSaleInfoPageRes;
import com.dd.cloud.user.service.admin.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Lx
 * @version 1.0
 */
@Slf4j
@Service
public class AdminSaleInfoServiceImpl extends ServiceImpl<AdminSaleInfoMapper, AdminSaleInfo> implements IAdminSaleInfoService {
    @Autowired
    private IAdminUserService adminUserService;
    @Autowired
    private AuthFeignService authFeignService;
    @Autowired
    private ISaleInviteDoctorService saleInviteDoctorService;
    @Autowired
    private ISaleInviteAgentService saleInviteAgentService;
    @Autowired
    private ISaleInviteMechanService saleInviteMechanService;

    /**
     * 查询管理员销售列表
     *
     * @param req
     * @return
     */
    @Override
    public IPage<AdminSaleInfoPageRes> queryAdminSaleInfoPage(AdminSaleInfoPageReq req) {
        Assert.verifyStatusIdsParam(req.getClass(), req);
        if (StringUtils.isBlank(req.getStatus())) {
            req.setStatus(AdminConstants.UserStatus.NORMAL + "," + AdminConstants.UserStatus.DISABLEADMIN);
        }
        if (String.valueOf(AdminConstants.UserStatus.LOG_OUT).equals(req.getStatus())) {
            req.setCountStatus(AdminConstants.UserStatus.DEL);
        }
        IPage<AdminSaleInfoPageRes> iPage = req.pagePojo();
        iPage = getBaseMapper().queryAdminSaleInfoPage(iPage, req);
        for (AdminSaleInfoPageRes item : iPage.getRecords()) {
            item.setTotalOrderCount(item.getTotalOrderCount() + item.getOrderCount());
            item.setTotalMechanCount(item.getTotalMechanCount() + item.getMechanCount());
            item.setTotalDoctorCount(item.getTotalDoctorCount() + item.getDoctorCount());
        }
        return iPage;
    }

    /**
     * 创建销售管理员
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createAdminSaleInfo(AdminSaleInfoCreateReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.ADMIN).get();
        QueryWrapper<AdminUser> qw = new QueryWrapper<>();
        qw.lambda().notIn(AdminUser::getStatus, AdminConstants.UserStatus.DEL, AdminConstants.UserStatus.LOG_OUT);
        qw.lambda().and(t -> t.eq(AdminUser::getAccount, req.getMobileNumber()).or().eq(AdminUser::getPhone, req.getMobileNumber()));
        int count = adminUserService.count(qw);
        if (count > 0) {
            throw new ZekeException(400, "该手机号账号已被占用");
        }
        AdminUser adminUser = new AdminUser();
        adminUser.setAccount(req.getMobileNumber());
        adminUser.setPhone(req.getMobileNumber());
        adminUser.setNickName(req.getName());
        adminUser.setEmail(req.getEmail());
        String salt = CodecUtils.generateSalt();
        adminUser.setSalt(salt);
        adminUser.setPassword(CodecUtils.md5Hex(req.getMobileNumber().substring(5), salt));
        adminUser.setType(AdminConstants.UserType.SALE);
        adminUser.setStatus(AdminConstants.UserStatus.NORMAL);
        adminUser.setCreateId(loginInfo.getId());
        adminUser.setCreateName(loginInfo.getName());
        adminUser.setCreateDate(LocalDateTime.now());
        boolean flag = adminUserService.save(adminUser);
        if (!flag) {
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
        /**
         * 设置销售管理员的权限
         */
        //adminPowerService.bindUserRole(adminUser.getId(), req.getRoleId(), LoginInfo.UserType.ADMIN);
        authFeignService.userBindRole(new UserBindRoleReq(adminUser.getId(), null, LoginInfo.UserType.ADMIN, "销售管理员"));


        AdminSaleInfo adminSaleInfo = new AdminSaleInfo();
        BeanUtils.copyProperties(req, adminSaleInfo);
        adminSaleInfo.setAdminId(adminUser.getId());
        adminSaleInfo.setStatus(AdminConstants.SaleInfoStatus.NORMAL);
        adminSaleInfo.setCreateId(loginInfo.getId());
        adminSaleInfo.setCreateName(loginInfo.getName());
        adminSaleInfo.setCreateDate(LocalDateTime.now());
        adminSaleInfo.setInviteCode(HealthConstants.InviteCodePrefixConstants.SALE_PREFIX + SerialNumberUtils.generatorInviteCode(adminUser.getId(), 5));
        flag = save(adminSaleInfo);
        if (!flag) {
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
    }

    /**
     * 修改销售管理员
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAdminSaleInfo(AdminSaleInfoUpdateReq req) {
        UserInterceptor.getLoginUserInfo(LoginInfo.UserType.ADMIN).get();
        QueryWrapper<AdminUser> qw = new QueryWrapper<>();
        qw.lambda().notIn(AdminUser::getStatus, AdminConstants.UserStatus.DEL, AdminConstants.UserStatus.LOG_OUT);
        qw.lambda().ne(AdminUser::getId, req.getId());
        qw.lambda().and(t -> t.eq(AdminUser::getAccount, req.getMobileNumber()).or().eq(AdminUser::getPhone, req.getMobileNumber()));
        int count = adminUserService.count(qw);
        if (count > 0) {
            throw new ZekeException(400, "该手机号账号已被占用");
        }
        AdminUser adminUser = new AdminUser();
        adminUser.setId(req.getId());
        adminUser.setAccount(req.getMobileNumber());
        adminUser.setPhone(req.getMobileNumber());
        adminUser.setNickName(req.getName());
        adminUser.setEmail(req.getEmail());
        boolean flag = adminUserService.updateById(adminUser);
        if (!flag) {
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
        /**
         * 设置销售管理员的权限
         */
        authFeignService.userBindRole(new UserBindRoleReq(adminUser.getId(), null, LoginInfo.UserType.ADMIN, "销售管理员"));

        AdminSaleInfo adminSaleInfo = new AdminSaleInfo();
        BeanUtils.copyProperties(req, adminSaleInfo);
        QueryWrapper<AdminSaleInfo> qws = new QueryWrapper<>();
        qws.lambda().eq(AdminSaleInfo::getAdminId, adminUser.getId());
        flag = update(adminSaleInfo, qws);
        if (!flag) {
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
    }

    /**
     * 查询销售管理员详情
     *
     * @param saleId
     * @return
     */
    @Override
    public AdminSaleInfoDetailRes queryAdminSaleInfoDetail(Integer saleId) {
        if (saleId == null) {
            LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.ADMIN).get();
            saleId = loginInfo.getId();
        }
        Integer status = 1;
        AdminUser adminUser = adminUserService.getById(saleId);
        if (adminUser.getStatus() == AdminConstants.UserStatus.LOG_OUT) {
            status = -1;
        }
        AdminSaleInfoDetailRes res = getBaseMapper().queryAdminSaleInfoDetail(saleId, status);
        if (res != null) {
            res.setTotalOrderCount(res.getTotalOrderCount() + res.getOrderCount());
            res.setTotalDoctorCount(res.getTotalDoctorCount() + res.getDoctorCount());
            res.setTotalMechanCount(res.getTotalMechanCount() + res.getMechanCount());
        }
        return res;
    }

    /**
     * @param beId: 转交的销售人员id
     * @param toId: 接收的人员id
     * @return void
     * @description 销售人员转交客户数据 转交完成后转交的销售将被注销
     * @author czg
     * @date 2023/6/27 9:44
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saleJoin(Integer beId, Integer toId) {
        AdminUser beUser = adminUserService.getById(beId);
        if (beUser == null || beUser.getStatus() == AdminConstants.UserStatus.DEL || beUser.getStatus() == AdminConstants.UserStatus.LOG_OUT) {
            throw new ZekeException("转交的销售人员id不存在");
        }
        QueryWrapper<AdminSaleInfo> qw = new QueryWrapper<>();
        qw.lambda().eq(AdminSaleInfo::getAdminId, beUser.getId())
                .eq(AdminSaleInfo::getStatus, AdminConstants.SaleInfoStatus.NORMAL);
        AdminSaleInfo one = getOne(qw);
        if (one == null) {
            throw new ZekeException("转交的销售人员不存在");
        }
        AdminUser toUser = adminUserService.getById(toId);
        if (toUser == null) {
            throw new ZekeException("接收的销售人员id不存在");
        }
        if (toUser == null || toUser.getStatus() == AdminConstants.UserStatus.DEL || toUser.getStatus() == AdminConstants.UserStatus.LOG_OUT) {
            throw new ZekeException("接收的销售人员id不存在");
        }
        if (toUser.getStatus() == AdminConstants.UserStatus.DISABLEADMIN) {
            throw new ZekeException("接收的销售人员已被禁用,请先解除禁用");
        }
        qw.clear();
        qw.lambda().eq(AdminSaleInfo::getAdminId, toUser.getId())
                .eq(AdminSaleInfo::getStatus, AdminConstants.SaleInfoStatus.NORMAL);
        AdminSaleInfo toOne = getOne(qw);
        if (toOne == null) {
            throw new ZekeException("接收的销售人员不存在");
        }
        /**
         * 修改销售绑定的医生
         * 1,删除原销售人员绑定的医生, 方便查询注销的数据
         * 2,添加原绑定的医生到新的销售人员
         */
        QueryWrapper<SaleInviteDoctor> qs = new QueryWrapper<>();
        qs.lambda().eq(SaleInviteDoctor::getSaleId, beUser.getId())
                .eq(SaleInviteDoctor::getStatus, AdminConstants.SaleInviteStatus.NORMAL);
        List<SaleInviteDoctor> inviteDoctors = saleInviteDoctorService.list(qs);
        if (inviteDoctors != null && !inviteDoctors.isEmpty()) {
            inviteDoctors = inviteDoctors.stream().map(item -> {
                item.setStatus(AdminConstants.SaleInviteStatus.DEL);
                return item;
            }).collect(Collectors.toList());
            boolean b = saleInviteDoctorService.updateBatchById(inviteDoctors);
            if (!b) {
                throw new ZekeException("修改转交医生失败");
            }
            inviteDoctors = inviteDoctors.stream().map(item -> {
                item.setStatus(AdminConstants.SaleInviteStatus.NORMAL);
                item.setSaleId(toUser.getId());
                item.setCreateDate(LocalDateTime.now());
                item.setRemark(one.getName() + "转交");
                item.setId(null);
                item.setIsTransmitted(1);
                return item;
            }).collect(Collectors.toList());
            saleInviteDoctorService.saveBatchByList(inviteDoctors);
        }

        /**
         * 修改销售绑定的机构
         */
        QueryWrapper<SaleInviteMechan> qm = new QueryWrapper<>();
        qm.lambda().eq(SaleInviteMechan::getSaleId, beUser.getId())
                .eq(SaleInviteMechan::getStatus, AdminConstants.SaleInviteStatus.NORMAL);
        List<SaleInviteMechan> inviteMechans = saleInviteMechanService.list(qm);
        if (inviteMechans != null && !inviteMechans.isEmpty()) {
            inviteMechans = inviteMechans.stream().map(item -> {
                item.setStatus(AdminConstants.SaleInviteStatus.DEL);
                return item;
            }).collect(Collectors.toList());
            boolean b = saleInviteMechanService.updateBatchById(inviteMechans);
            if (!b) {
                throw new ZekeException("修改转交机构失败");
            }

            inviteMechans = inviteMechans.stream().map(item -> {
                item.setStatus(AdminConstants.SaleInviteStatus.NORMAL);
                item.setSaleId(toUser.getId());
                item.setCreateDate(LocalDateTime.now());
                item.setRemark(one.getName() + "转交");
                item.setIsTransmitted(1);
                item.setId(null);
                return item;
            }).collect(Collectors.toList());
            boolean saveBatch = saleInviteMechanService.saveBatch(inviteMechans);
            if (!saveBatch) {
                throw new ZekeException("添加转交机构失败");
            }
        }

        /**
         * 修改销售绑定的代理商
         */
        QueryWrapper<SaleInviteAgent> qa = new QueryWrapper<>();
        qa.lambda().eq(SaleInviteAgent::getSaleId, beUser.getId())
                .eq(SaleInviteAgent::getStatus, AdminConstants.SaleInviteStatus.NORMAL);
        List<SaleInviteAgent> inviteAgents = saleInviteAgentService.list(qa);
        if (inviteAgents != null && !inviteAgents.isEmpty()) {
            inviteAgents = inviteAgents.stream().map(item -> {
                item.setStatus(AdminConstants.SaleInviteStatus.DEL);
                return item;
            }).collect(Collectors.toList());
            boolean b = saleInviteAgentService.updateBatchById(inviteAgents);
            if (!b) {
                throw new ZekeException("修改转交代理商失败");
            }

            inviteAgents = inviteAgents.stream().map(item -> {
                item.setStatus(AdminConstants.SaleInviteStatus.NORMAL);
                item.setSaleId(toUser.getId());
                item.setCreateDate(LocalDateTime.now());
                item.setRemark(one.getName() + "转交");
                item.setIsTransmitted(1);
                item.setId(null);
                return item;
            }).collect(Collectors.toList());
            boolean saveBatch = saleInviteAgentService.saveBatch(inviteAgents);
            if (!saveBatch) {
                throw new ZekeException("添加转交代理商失败");
            }
        }

        /**
         * 注销原销售人员
         */
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        beUser.setStatus(AdminConstants.UserStatus.LOG_OUT);
        beUser.setLogOutName(loginInfo.getName());
        beUser.setLogOutDate(LocalDateTime.now());
        beUser.setTransferId(toId);
        beUser.setTransferName(toUser.getNickName());
        boolean updateById = adminUserService.updateById(beUser);
        if (!updateById) {
            throw new ZekeException("注销销售人员失败");
        }
        one.setStatus(AdminConstants.SaleInfoStatus.DEL);
        updateById = updateById(one);
        if (!updateById) {
            throw new ZekeException("注销销售人员失败");
        }
    }
}
